/*
 The NIST RCS (Real-time Control Systems)
 library is public domain software, however it is preferred
 that the following disclaimers be attached.

 Software Copywrite/Warranty Disclaimer

 This software was developed at the National Institute of Standards and
 Technology by employees of the Federal Government in the course of their
 official duties. Pursuant to title 17 Section 105 of the United States
 Code this software is not subject to copyright protection and is in the
 public domain. NIST Real-Time Control System software is an experimental
 system. NIST assumes no responsibility whatsoever for its use by other
 parties, and makes no guarantees, expressed or implied, about its
 quality, reliability, or any other characteristic. We would appreciate
 acknowledgement if the software is used. This software can be
 redistributed and/or modified freely provided that any derivative works
 bear some notice that they are derived from it, and any modified
 versions bear some notice that they have been modified. 

 */
/*
 * plotterJFrame.java
 *
 * Created on December 31, 2006, 7:20 AM
 */
package diagapplet.plotter;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.UIManager;

/**
 * Seperate Frame with only a plotter_NB_UI inside.
 *
 * @author Will Shackleford
 */
public class plotterJFrame extends javax.swing.JFrame {

    private static final long serialVersionUID = 2613933L;
    private File recentFile = null;
    private Vector<String> recentVector = null;
    private String args[] = null;
    private File last_dir = null;

    /**
     * Creates new form plotterJFrame
     */
    public plotterJFrame() {
        initComponents();
        ReadRecentVector();
        LoadArgs();
        SetIcon();
        this.jCheckBoxMenuItemDebug.setState(PlotterCommon.debug_on);
    }

    public plotterJFrame(final String _args[]) {
        this.args = _args;
        initComponents();
        ReadRecentVector();
        LoadArgs();
        SetIcon();
        this.jCheckBoxMenuItemDebug.setState(PlotterCommon.debug_on);
    }

    public BufferedImage plotToImage() {
        return this.plotter_NB_UI1.plotToImage();
    }

    public BufferedImage plotToImage(int width, int height) {
        return this.plotter_NB_UI1.plotToImage(width, height);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        plotter_NB_UI1 = new diagapplet.plotter.plotter_NB_UI();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenuFile = new javax.swing.JMenu();
        jMenuItemFileOpen = new javax.swing.JMenuItem();
        jMenuFileRecent = new javax.swing.JMenu();
        jMenuTests = new javax.swing.JMenu();
        jMenuItemSineTest = new javax.swing.JMenuItem();
        jMenuItemRandomTest = new javax.swing.JMenuItem();
        jMenuItemRandomContinous = new javax.swing.JMenuItem();
        jMenuItemStopRandomContinous = new javax.swing.JMenuItem();
        jMenuItemSave = new javax.swing.JMenuItem();
        jMenuItemSaveImage = new javax.swing.JMenuItem();
        jMenuItemExit = new javax.swing.JMenuItem();
        jMenuItemReload = new javax.swing.JMenuItem();
        jMenuExtras = new javax.swing.JMenu();
        jMenuItemResetMinXToZero = new javax.swing.JMenuItem();
        jCheckBoxMenuItemDebug = new javax.swing.JCheckBoxMenuItem();
        jMenuItemShowDataFrame = new javax.swing.JMenuItem();
        jMenuItemShowOptions = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Plotter");

        jMenuFile.setText("File");

        jMenuItemFileOpen.setText("Open");
        jMenuItemFileOpen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemFileOpenActionPerformed(evt);
            }
        });
        jMenuFile.add(jMenuItemFileOpen);

        jMenuFileRecent.setText("Recent");
        jMenuFile.add(jMenuFileRecent);

        jMenuTests.setText("Tests");

        jMenuItemSineTest.setText("Sine Test");
        jMenuItemSineTest.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemSineTestActionPerformed(evt);
            }
        });
        jMenuTests.add(jMenuItemSineTest);

        jMenuItemRandomTest.setText("Random Test");
        jMenuItemRandomTest.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemRandomTestActionPerformed(evt);
            }
        });
        jMenuTests.add(jMenuItemRandomTest);

        jMenuItemRandomContinous.setText("Random Continous");
        jMenuItemRandomContinous.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemRandomContinousActionPerformed(evt);
            }
        });
        jMenuTests.add(jMenuItemRandomContinous);

        jMenuItemStopRandomContinous.setText("Stop Random Continous");
        jMenuItemStopRandomContinous.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemStopRandomContinousActionPerformed(evt);
            }
        });
        jMenuTests.add(jMenuItemStopRandomContinous);

        jMenuFile.add(jMenuTests);

        jMenuItemSave.setText(" Save As . . .");
        jMenuItemSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemSaveActionPerformed(evt);
            }
        });
        jMenuFile.add(jMenuItemSave);

        jMenuItemSaveImage.setText("Save Image As ...");
        jMenuItemSaveImage.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemSaveImageActionPerformed(evt);
            }
        });
        jMenuFile.add(jMenuItemSaveImage);

        jMenuItemExit.setText("Exit");
        jMenuItemExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemExitActionPerformed(evt);
            }
        });
        jMenuFile.add(jMenuItemExit);

        jMenuItemReload.setText("Reload");
        jMenuItemReload.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemReloadActionPerformed(evt);
            }
        });
        jMenuFile.add(jMenuItemReload);

        jMenuBar1.add(jMenuFile);

        jMenuExtras.setText("Extras");

        jMenuItemResetMinXToZero.setText("Reset Min X to Zero");
        jMenuItemResetMinXToZero.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemResetMinXToZeroActionPerformed(evt);
            }
        });
        jMenuExtras.add(jMenuItemResetMinXToZero);

        jCheckBoxMenuItemDebug.setText("Debug");
        jCheckBoxMenuItemDebug.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jCheckBoxMenuItemDebugActionPerformed(evt);
            }
        });
        jMenuExtras.add(jCheckBoxMenuItemDebug);

        jMenuItemShowDataFrame.setText(" Show Data Frame");
        jMenuItemShowDataFrame.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemShowDataFrameActionPerformed(evt);
            }
        });
        jMenuExtras.add(jMenuItemShowDataFrame);

        jMenuItemShowOptions.setText("Show Options");
        jMenuItemShowOptions.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemShowOptionsActionPerformed(evt);
            }
        });
        jMenuExtras.add(jMenuItemShowOptions);

        jMenuBar1.add(jMenuExtras);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(plotter_NB_UI1, javax.swing.GroupLayout.PREFERRED_SIZE, 968, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(plotter_NB_UI1, javax.swing.GroupLayout.DEFAULT_SIZE, 384, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jMenuItemReloadActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemReloadActionPerformed
    {//GEN-HEADEREND:event_jMenuItemReloadActionPerformed
        if (null != plotter_NB_UI1) {
            plotter_NB_UI1.ReloadFile();
        }
    }//GEN-LAST:event_jMenuItemReloadActionPerformed

    public void SetEqualizeAxis(boolean _e_mode) {
        this.plotter_NB_UI1.SetEqualizeAxis(_e_mode);
    }

    private void jMenuItemSaveActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemSaveActionPerformed
    {//GEN-HEADEREND:event_jMenuItemSaveActionPerformed
        javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() {

            public boolean accept(File f) {
                return (!f.isHidden() && !f.getName().startsWith("."));
            }

            public String getDescription() {
                return "Plot Data Files";
            }
        };
        JFileChooser chooser = new JFileChooser();
        if (last_dir != null) {
            chooser.setCurrentDirectory(last_dir);
        } else {
            chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
        }
        chooser.setFileFilter(filter);
        int returnVal = chooser.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            System.out.println("You chose to open this file: "
                    + chooser.getSelectedFile().getPath());
            last_dir = chooser.getCurrentDirectory();
            SaveToRecentVector(chooser.getSelectedFile().getPath());
            plotter_NB_UI1.SaveFile(chooser.getSelectedFile().getPath());
        }
    }//GEN-LAST:event_jMenuItemSaveActionPerformed

    private void jMenuItemExitActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemExitActionPerformed
    {//GEN-HEADEREND:event_jMenuItemExitActionPerformed
        System.exit(0);
    }//GEN-LAST:event_jMenuItemExitActionPerformed
    private boolean auto_fit_to_graph = true;

    public void set_auto_fit_to_graph(final boolean _auto_fit_to_graph) {
        this.auto_fit_to_graph = _auto_fit_to_graph;
        if (null != this.plotter_NB_UI1) {
            this.plotter_NB_UI1.set_auto_fit_to_graph(_auto_fit_to_graph);
        }
    }

    public void SetGraphLimits(double new_x_show_area_min,
            double new_x_show_area_max,
            double new_y_show_area_min,
            double new_y_show_area_max) {
        this.plotter_NB_UI1.SetGraphLimits(new_x_show_area_min,
                new_x_show_area_max,
                new_y_show_area_min,
                new_y_show_area_max);
    }

    public void setGraphFunction(int i) {
        this.plotter_NB_UI1.setGraphFunction(i);
    }

    public void setGraphFunction(String s) {
        this.plotter_NB_UI1.setGraphFunction(s);
    }

    public void setFuncArg(int i) {
        this.plotter_NB_UI1.setFuncArg(i);
    }

    private void LoadArgs() {
        boolean arg_ends_in_xy = false;
        PlotLoader.filenum = 0;
        if (null != args) {
            boolean skip_next_arg = false;
            boolean next_arg_is_geometry = false;
            for (String arg : args) {
                if (arg.length() < 1) {
                    continue;
                }
                System.out.println("arg=" + arg);
                if (skip_next_arg) {
                    skip_next_arg = false;
                    continue;
                }
                if (next_arg_is_geometry) {
                    int x_index = arg.indexOf('x');
                    if (x_index < 1) {
                        System.err.println("Bad geometry: " + arg);
                        next_arg_is_geometry = false;
                        continue;
                    }
                    String w = arg.substring(0, x_index);
                    String h = arg.substring(x_index + 1);
                    int plus_index = h.indexOf('+', 1);
                    if (plus_index > 0) {
                        h = h.substring(0, plus_index);
                    }
                    int new_width = Integer.valueOf(w).intValue();
                    int new_height = Integer.valueOf(h).intValue();
                    this.setSize(new_width, new_height);
                    next_arg_is_geometry = false;
                    continue;
                }
                if (arg.charAt(0) == '-') {
                    if (arg.startsWith("--FieldSelectPattern=")) {
                        plotter_NB_UI1.setFieldSelectPattern(arg.substring(21));
                    } else if (arg.startsWith("--FieldSeparator=")) {
                        PlotLoader.setFieldSeparator(arg.substring(17));
                    } else if (arg.startsWith("--Function=")) {
                        this.setGraphFunction(arg.substring(11));
                    } else if (arg.startsWith("--FunctionArg=")) {
                        String fa = arg.substring(14);
                        this.plotter_NB_UI1.setFuncArg(fa);
                    } else if (arg.startsWith("--showKey")) {
                        this.plotter_NB_UI1.setShowKey(true);
                    } else if (arg.startsWith("--hideKey")) {
                        this.plotter_NB_UI1.setShowKey(false);
                    } else if (arg.startsWith("--split")) {
                        this.plotter_NB_UI1.setNosplit(false);
                        this.plotter_NB_UI1.setSplit(true);
                    } else if (arg.startsWith("--nosplit")) {
                        this.plotter_NB_UI1.setNosplit(true);
                    } else if (arg.startsWith("--hide")) {
                        this.setVisible(false);
                    } else if (arg.startsWith("--reverseX")) {
                        plotter_NB_UI1.SetReverseX(true);
                    } else if (arg.startsWith("--timeDiffMin=")) {
                        PlotLoader.set_time_diff_min(Double.valueOf(arg.substring(14)));
                    } else if (arg.startsWith("--plotVsLineNumber=")) {
                        PlotLoader.set_plot_verses_line_number(Boolean.valueOf(arg.substring(19)));
                    } else if (arg.startsWith("--useReverseLineNumber=")) {
                        PlotLoader.set_use_reverse_line_number(Boolean.valueOf(arg.substring(23)));
                    } else if (arg.startsWith("--startAtLineNumber=")) {
                        PlotLoader.set_start_at_line_number(Integer.valueOf(arg.substring(20)));
                    } else if (arg.startsWith("--endAtLineNumber=")) {
                        PlotLoader.set_end_at_line_number(Integer.valueOf(arg.substring(18)));
                    } else if (arg.startsWith("--showPointsLimit=")) {
                        plotter_NB_UI1.set_point_size_limit(Integer.valueOf(arg.substring(18)));
                    } else if (arg.startsWith("--setPlotOrder=")) {
                        plotter_NB_UI1.setPlot_order(arg.substring(15));
                    } else if (arg.startsWith("--cmdLineMode")) {
                        PlotLoader.cmd_line_mode = true;
                    } else if (arg.startsWith("--disposeOnClose")) {
                        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    } else if (arg.startsWith("--geometry")) {
                        next_arg_is_geometry = true;
                    } else if (arg.compareTo("-o") == 0) {
                        this.setVisible(false);
                        skip_next_arg = true;
                    } else {
                        System.err.println("Unrecognized command line argument:" + arg);

                        System.err.println("Possible Options:");
                        System.err.println("\t--FieldSelectPattern=");
                        System.err.println("\t--FieldSeparator=");
                        System.err.println("\t--Function=");
                        System.err.println("\t--FunctionArg=");
                        System.err.println("\t--showKey");
                        System.err.println("\t--hideKey");
                        System.err.println("\t--split");
                        System.err.println("\t--nosplit");
                        System.err.println("\t--hide");
                        System.err.println("\t--reverseX");
                        System.err.println("\t--timeDiffMin=");
                        System.err.println("\t--plotVsLineNumber=");
                        System.err.println("\t--showPointsLimit=");
                        System.err.println("\t--startLineNumber=");
                        System.err.println("\t--endLineNumber=");
                        System.err.println("\t--geometry");
                        System.err.println("\t-o");
                        System.exit(1);
                    }
                    continue;
                }
                arg = arg.trim();
                if (arg.length() < 1) {
                    continue;
                }
                //System.out.println("arg="+arg);
                if (arg.charAt(0) == '.') {
                    System.err.println("Relative path names are not recommended.\nPlease use absolute path for " + arg);
                }
                LoadFile(arg);
                PlotLoader.filenum++;
//		plotter_NB_UI1.loadFile(arg);
//                this.setTitle("Plotter "+arg+ " ( "+this.plotter_NB_UI1.get_num_plots()+" ) ");
                arg_ends_in_xy = arg.endsWith(".xy");
                try {
                    File f = new File(arg);
                    if (f.exists()) {
                        this.SaveToRecentVector(f.getCanonicalPath());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (auto_fit_to_graph) {
                plotter_NB_UI1.FitToGraph();
            }
            if (arg_ends_in_xy) {
                plotter_NB_UI1.setGraphFunctionXY();
                plotter_NB_UI1.ForceRecheckComboFunc();
            }
        }
    }

    private void CleanRecentVector() throws Exception {
        for (int i = 0; i < recentVector.size() && recentVector.size() > 0; i++) {
            if (!(new File(recentVector.elementAt(i)).exists())) {
                recentVector.remove(i);
                i--;
                continue;
            }
        }
        for (int i = 0; i < recentVector.size() && recentVector.size() > 0; i++) {
            String istring = recentVector.elementAt(i);
            for (int j = i + 1; j < recentVector.size(); j++) {
                String jstring = recentVector.elementAt(j);
                if (istring.compareTo(jstring) == 0) {
                    recentVector.remove(j);
                    j--;
                    continue;
                }
            }
        }
        List<String> recentVectorList = recentVector.subList(0, recentVector.size());
        Collections.sort(recentVectorList,
                new Comparator<String>() {

                    public int compare(String o1, String o2) {
                        return o1.compareTo(o2);
                    }
                });
        recentVector = new Vector(recentVectorList);
    }

    @SuppressWarnings("unchecked")
    private void ReadRecentVector() {
        recentFile = new File(System.getProperty("user.home"), ".plotter_recent_files.xml");
        try {
            if (recentFile.exists() && recentFile.canRead()) {
                XMLDecoder decoder = new XMLDecoder(
                        new BufferedInputStream(
                                new FileInputStream(recentFile)));
                recentVector = (Vector<String>) decoder.readObject();
                CleanRecentVector();
                decoder.close();
                for (String s : recentVector) {
                    if (!new File(s).exists()) {
                        continue;
                    }
                    JMenuItem jmi = new JMenuItem(s);
                    jmi.addActionListener(new ActionListener() {

                        public void actionPerformed(ActionEvent e) {
                            String fname = ((JMenuItem) e.getSource()).getText();
                            PlotLoader.filenum = 0;
                            LoadFile(fname);
//                            plotter_NB_UI1.loadFile(fname);
//                            setTitle("Plotter "+fname+ " ( "+plotter_NB_UI1.get_num_plots()+" ) ");
//                            plotter_NB_UI1.FitToGraph();
//                            if(fname.endsWith(".xy"))
//                            {
//                                plotter_NB_UI1.setGraphFunctionXY();
//                            }
                        }
                    });
                    jMenuFileRecent.add(jmi);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (null == recentVector) {
            recentVector = new Vector<String>();
        }
    }

    private void SetIcon() {
        try {
            java.net.URL icon_url = this.getClass().getClassLoader().getResource("diagapplet/plotter/plottericon.jpg");
//	    icon_url=ClassLoader.getSystemClassLoader().getResource("diagapplet/plotter/plottericon.png");
//	    ClassLoader.getSystemResource("diagapplet/plotter/plottericon.png");
//	    if(null == icon_url)
//	    {
//		icon_url=ClassLoader.getSystemResource("diagapplet/plotter/plottericon.jpg");
//	    }
//	    if(null == icon_url)
//	    {
//		icon_url=ClassLoader.getSystemResource("plottericon.jpg");
//	    }
//	    icon_url=
//	    if(null == icon_url)
//	    {
//		icon_url=ClassLoader.getSystemClassLoader().getResource("diagapplet/plotter/plottericon.jpg");
//	    }
//	    if(null == icon_url)
//	    {
//		icon_url=ClassLoader.getSystemClassLoader().getResource("plottericon.jpg");
//	    }
//	    if(null == icon_url)
//	    {
//		icon_url= this.getClass().getClassLoader().getSystemResource("diagapplet/plotter/plottericon.png");
//	    }
//	    if(null == icon_url)
//	    {
//		icon_url=this.getClass().getClassLoader() .getSystemResource("diagapplet/plotter/plottericon.jpg");
//	    }
//	    if(null == icon_url)
//	    {
//		icon_url=this.getClass().getClassLoader() .getSystemResource("plottericon.jpg");
//	    }
//	    if(null == icon_url)
//	    {
//		icon_url= this.getClass().getClassLoader().getResource("diagapplet/plotter/plottericon.png");
//	    }
//	    if(null == icon_url)
//	    {
//
//	    }
//	    if(null == icon_url)
//	    {
//		icon_url=this.getClass().getClassLoader() .getResource("plottericon.jpg");
//	    }
            if (null != icon_url) {
                this.setIconImage(javax.imageio.ImageIO.read(icon_url.openStream()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void SaveToRecentVector(String s) {
        try {
            CleanRecentVector();
            while (recentVector.size() > 20) {
                recentVector.remove(0);
            }
            recentVector.add(s);
            JMenuItem recentMenuItemToAdd = new JMenuItem(s);
            recentMenuItemToAdd.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    String fname = ((JMenuItem) e.getSource()).getText();
                    PlotLoader.filenum = 0;
                    LoadFile(fname);
//                    plotter_NB_UI1.loadFile(fname);
//                    setTitle("Plotter "+fname+ " ( "+plotter_NB_UI1.get_num_plots()+" ) ");
//                    if(fname.endsWith(".xy"))
//                    {
//                        plotter_NB_UI1.setGraphFunctionXY();
//                    }
                }
            });
            jMenuFileRecent.add(recentMenuItemToAdd);
            XMLEncoder encoder = new XMLEncoder(
                    new BufferedOutputStream(
                            new FileOutputStream(recentFile)));
            encoder.writeObject(recentVector);
            encoder.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private int rnum = 0;
    private void jMenuItemRandomTestActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemRandomTestActionPerformed
    {//GEN-HEADEREND:event_jMenuItemRandomTestActionPerformed
        PlotData pd = new PlotData();
        pd.name = "Random_Test" + rnum;
        rnum++;
        plotter_NB_UI1.AddPlot(pd);
        Random r = new Random();
        double y = 0.0;
        for (int i = 0; i < 3000; i++) {
            y += r.nextDouble() - 0.5;
            plotter_NB_UI1.AddPointToPlot(pd, (i / 600.0), y, true);
        }
        plotter_NB_UI1.SetOuterArea(-1.0, 2.0, -2.0, 2.0);
        plotter_NB_UI1.SetInnerArea(-2.0, 2.0, -2.0, 2.0);
    }//GEN-LAST:event_jMenuItemRandomTestActionPerformed

    private void jMenuItemSineTestActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemSineTestActionPerformed
    {//GEN-HEADEREND:event_jMenuItemSineTestActionPerformed
        PlotData pd = new PlotData();
        pd.name = "Sine_Test";
        plotter_NB_UI1.AddPlot(pd);
        for (int i = 0; i < 2000; i++) {
            plotter_NB_UI1.AddPointToPlot(pd, (i / 600.0), Math.sin((i / 100.0)), true);
        }
        plotter_NB_UI1.SetOuterArea(-1.0, 2.0, -2.0, 2.0);
        plotter_NB_UI1.SetInnerArea(-2.0, 2.0, -2.0, 2.0);
    }//GEN-LAST:event_jMenuItemSineTestActionPerformed

    private void jMenuItemFileOpenActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemFileOpenActionPerformed
    {//GEN-HEADEREND:event_jMenuItemFileOpenActionPerformed
        javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() {

            public boolean accept(File f) {
                return (!f.isHidden() && !f.getName().startsWith("."));
            }

            public String getDescription() {
                return "Plot Data Files";
            }
        };
        JFileChooser chooser = new JFileChooser();
        if (last_dir != null) {
            chooser.setCurrentDirectory(last_dir);
        } else {
            chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
        }
        chooser.setMultiSelectionEnabled(true);
        chooser.setFileFilter(filter);
        int returnVal = chooser.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            System.out.println("You chose to open this file: "
                    + chooser.getSelectedFile().getPath());
            last_dir = chooser.getCurrentDirectory();
            PlotLoader.filenum = 0;
            for (File f : chooser.getSelectedFiles()) {
                SaveToRecentVector(f.getPath());
                String fname = f.getPath();
                LoadFile(fname);
                PlotLoader.filenum++;
            }
        }
    }//GEN-LAST:event_jMenuItemFileOpenActionPerformed
    private double random_i = 0;
    private Random random_r = new Random();
    private javax.swing.Timer random_swing_timer = null;
    private double random_y = 0;
    private PlotData random_pd = null;

    public void setSplit(boolean _new_s_mode) {
        this.plotter_NB_UI1.setNosplit(false);
        this.plotter_NB_UI1.setSplit(_new_s_mode);
    }

    public PlotData getPlotByName(String name) {
        return this.plotter_NB_UI1.getPlotByName(name);
    }
    
    public void AddPointToPlot(PlotData pd, double pre_f_x, double pre_f_y, boolean connected) {
        this.plotter_NB_UI1.AddPointToPlot(pd, pre_f_x, pre_f_y, connected);
    }

    public void AddPointToArrayPlot(PlotData pd, int index, double pre_f_y) {
        this.plotter_NB_UI1.AddPointToArrayPlot(pd, index, pre_f_y);
    }

//    public void AddPointToPlot(PlotData pd, double x, double y, boolean connected, double pre_f_x, double pre_f_y) {
//	this.plotter_NB_UI1.AddPointToPlot(pd, x, y, connected, pre_f_x, pre_f_y);
//    }
    public void AddPlot(PlotData pd) {
        this.plotter_NB_UI1.AddPlot(pd);
    }

    public void AddPlot(PlotData pd, String name) {
        this.plotter_NB_UI1.AddPlot(pd, name);
    }

    public void FitY() {
        if (!this.plotter_NB_UI1.get_paused()) {
            this.plotter_NB_UI1.FitY();
        }
    }

    public void FitToGraph() {
        if (!this.plotter_NB_UI1.get_paused()) {
            this.plotter_NB_UI1.FitToGraph();
        }
    }

    public void ScrollRight() {
        if (!this.plotter_NB_UI1.get_paused()) {
            this.plotter_NB_UI1.ScrollRight();
        }
    }

    public boolean is_paused() {
        return this.plotter_NB_UI1.get_paused();
    }

private void jMenuItemRandomContinousActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemRandomContinousActionPerformed
    random_pd = new PlotData();
    random_pd.name = "Random_Continous_Test" + rnum;
    rnum++;
    plotter_NB_UI1.AddPlot(random_pd);
    random_r = new Random();
    random_i = 0;
    random_swing_timer = new javax.swing.Timer(200, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            for (int i = 0; i < 20; i++) {
                random_i++;
                double x = random_i / 600.0;
                random_y += random_r.nextDouble() - 0.5;
//                System.out.println("x = " + x);
                plotter_NB_UI1.AddPointToPlot(random_pd, x, random_y, true);
                plotter_NB_UI1.FitY();
                plotter_NB_UI1.ScrollRight();
            }
        }
    });
    random_swing_timer.start();
}//GEN-LAST:event_jMenuItemRandomContinousActionPerformed

private void jMenuItemStopRandomContinousActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemStopRandomContinousActionPerformed
    if (this.random_swing_timer != null) {
        this.random_swing_timer.stop();
        this.random_swing_timer = null;
    }
}//GEN-LAST:event_jMenuItemStopRandomContinousActionPerformed

private void jMenuItemResetMinXToZeroActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemResetMinXToZeroActionPerformed
    this.plotter_NB_UI1.ResetMinXToZero();
}//GEN-LAST:event_jMenuItemResetMinXToZeroActionPerformed

private void jCheckBoxMenuItemDebugActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxMenuItemDebugActionPerformed
    PlotterCommon.debug_on = this.jCheckBoxMenuItemDebug.getState();
}//GEN-LAST:event_jCheckBoxMenuItemDebugActionPerformed

private void jMenuItemSaveImageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemSaveImageActionPerformed
    javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() {

        public boolean accept(File f) {
            return (!f.isHidden() && !f.getName().startsWith("."));
        }

        public String getDescription() {
            return "Plot Data Files";
        }
    };
    JFileChooser chooser = new JFileChooser();
    if (last_dir != null) {
        chooser.setCurrentDirectory(last_dir);
    } else {
        chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
    }
    chooser.setFileFilter(filter);
    int returnVal = chooser.showSaveDialog(this);
    if (returnVal == JFileChooser.APPROVE_OPTION) {
        System.out.println("You chose to open this file: "
                + chooser.getSelectedFile().getPath());
        last_dir = chooser.getCurrentDirectory();
        String output_filename = chooser.getSelectedFile().getPath();
        String name = chooser.getSelectedFile().getName();
        int lp = name.lastIndexOf(".");
        String ext = "PNG";
        if (lp < 0) {
            output_filename = output_filename + ".png";
            ext = "PNG";
        } else {
            ext = name.substring(lp + 1).toUpperCase();
        }
        BufferedImage bi = plotToImage();
        FileOutputStream fos = null;
        try {
            bi.flush();
            fos = new FileOutputStream(output_filename);
            ImageIO.write(bi, ext, fos);
            bi.flush();
            bi = null;
            System.out.println("size = " + fos.getChannel().size());
            fos.close();
            fos = null;
        } catch (Exception exception) {
            exception.printStackTrace();
        } finally {
            if (null != fos) {
                try {
                    fos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                fos = null;
            }
        }
    }
}//GEN-LAST:event_jMenuItemSaveImageActionPerformed

    private void jMenuItemShowDataFrameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemShowDataFrameActionPerformed
        this.plotter_NB_UI1.ShowData();
    }//GEN-LAST:event_jMenuItemShowDataFrameActionPerformed

    private void jMenuItemShowOptionsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemShowOptionsActionPerformed
        this.plotter_NB_UI1.ShowOptions();
    }//GEN-LAST:event_jMenuItemShowOptionsActionPerformed

    public void Clear() {
        plotter_NB_UI1.Clear();
    }

    /**
     * Open a new plotterFrame to show only this file.
     *
     * @param prefix string to look for in the names
     * @param xname name of X plot
     * @param l list of objects with xy data
     * @return the frame that was openned.
     * @throws java.lang.NoSuchFieldException when reflection fails
     */
    public static plotterJFrame ShowXYObjectsList(String prefix, String xname, List l)
            throws NoSuchFieldException {
        plotterJFrame frame = new plotterJFrame();
        frame.LoadXYObjectsList(prefix, xname, l);
        frame.setVisible(true);
        frame.FitToGraph();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        return frame;
    }

    public void LoadXYObjectsList(String prefix, String xname, List l)
            throws NoSuchFieldException {
        this.plotter_NB_UI1.LoadXYObjectsList(prefix, xname, l);
    }

    /**
     * Open a new plotterFrame to show only this file.
     *
     * @param prefix start of name to look for
     * @param l list of objects to plot
     * @return the frame that was openned.
     * @throws java.lang.NoSuchFieldException when obect reflection fails
     */
    public static plotterJFrame ShowObjectsList(String prefix, List l)
            throws NoSuchFieldException {
        plotterJFrame frame = new plotterJFrame();
        frame.LoadObjectsList(prefix, l);
        frame.setVisible(true);
        frame.FitToGraph();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        return frame;
    }

    public void LoadObjectsList(String prefix, List l)
            throws NoSuchFieldException {
        this.plotter_NB_UI1.LoadObjectsList(prefix, l);
    }

    /**
     * Loads two arrays into a single plot and displays it. The two arrays
     * should be the same length or points will only be plotted up to the
     * shorter of the two.
     *
     * @param name -- name of the plot
     * @param xA -- x axis array
     * @param yA -- y axis array
     */
    public void LoadXYFloatArrays(String name, float xA[], float yA[]) {
        if (xA == null) {
            plotter_NB_UI1.LoadFloatArray(name, yA);
        } else {
            plotter_NB_UI1.LoadXYFloatArrays(name, xA, yA);
        }
    }

    /**
     * Loads two arrays into a single plot and displays it. The two arrays
     * should be the same length or points will only be plotted up to the
     * shorter of the two.
     *
     * @param name -- name of the plot
     * @param xA -- x axis array
     * @param yA -- y axis array
     */
    public void LoadXYDoubleArrays(String name, double xA[], double yA[]) {
        if (xA == null) {
            plotter_NB_UI1.LoadDoubleArray(name, yA);
        } else {
            plotter_NB_UI1.LoadXYDoubleArrays(name, xA, yA);
        }
    }

    /**
     * Loads an arrays into a single plot and displays it.
     *
     * @param name -- name of the plot
     * @param fa -- float array to plot.
     */
    public void LoadFloatArray(String name, float fa[]) {
        plotter_NB_UI1.LoadFloatArray(name, fa);
    }

    /**
     * Loads an arrays into a single plot and displays it.
     *
     * @param name -- name of the plot
     * @param da -- double array to plot.
     */
    public void LoadDoubleArray(String name, double da[]) {
        plotter_NB_UI1.LoadDoubleArray(name, da);
    }

    /**
     * Open a new plotterFrame to show only this file.
     *
     * @param fname file name of csv file to plot
     * @return the frame that was openned.
     */
    public static plotterJFrame ShowFile(String fname) {
        plotterJFrame frame = new plotterJFrame();
        frame.LoadFile(fname);
        frame.setVisible(true);
        frame.FitToGraph();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        return frame;
    }

    /**
     * Open a new plotterFrame to show only this file.
     *
     * @param name name to give new plot
     * @param fa array of floats to plot
     * @return the frame that was openned.
     */
    public static plotterJFrame ShowFloatArray(String name, float fa[]) {
        plotterJFrame frame = new plotterJFrame();
        frame.LoadFloatArray(name, fa);
        frame.setVisible(true);
        frame.FitToGraph();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        return frame;
    }

    /**
     * Open a new plotterFrame to show only this file.
     *
     * @param name name of new plot
     * @param da array of doubles to plot
    * @return the frame that was openned.
     */
    public static plotterJFrame ShowDoubleArray(String name, double da[]) {
        plotterJFrame frame = new plotterJFrame();
        frame.LoadDoubleArray(name, da);
        frame.setVisible(true);
        frame.FitToGraph();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        return frame;
    }

    static public List<String> getLines(String filename, int max_lines) {
        try {
            LinkedList<String> lines = new LinkedList<String>();
            BufferedReader br = new BufferedReader(new FileReader(filename));
            String line = null;
            // Some idiot must be manually editing many of the files produced by
            // NDC8 Vehicle Application Designer
            // They instert month;..;min but in the header and then only 
            // put these fields in the first line. It is completely unneccessary and
            //  breaks any reasonable program for easy plotting.
            final String ndc8_workaround = "month;day;year;hour;min;,m.s.ms;";
            boolean using_ndc8_workaround = false;
            while (null != (line = br.readLine()) && (max_lines < 1 || lines.size() < max_lines)) {
                if (lines.size() == 0 && line.startsWith(ndc8_workaround)) {
                    line = "m.s.ms;" + line.substring(ndc8_workaround.length());
                    using_ndc8_workaround = true;
                }
                if (lines.size() == 1 && using_ndc8_workaround) {
                    line = line.substring(line.indexOf(";") + 1);
                    line = line.substring(line.indexOf(";") + 1);
                    line = line.substring(line.indexOf(";") + 1);
                    line = line.substring(line.indexOf(";") + 1);
                    line = line.substring(line.indexOf(";") + 1);
                }
                if(using_ndc8_workaround && line.startsWith(",")) {
                    line = line.substring(1);
                }
                lines.add(line);
            }
            br.close();
            return lines;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public void LoadFile(String fname) {
        try {
            if (!PlotLoader.cmd_line_mode) {
                List<String> lines = getLines(fname, 100);
                ParseOptions po = ParseOptionsJPanel.ask(null, this, lines);
                if (null != po) {
                    plotter_NB_UI1.setParseOptions(po);
                } else {
                    System.err.println("Loading of " + fname + " cancelled by user.");
                    return;
                }
            }
            plotter_NB_UI1.loadFile(fname);
            setTitle("Plotter " + fname + " ( " + plotter_NB_UI1.get_num_plots() + " ) ");
            if (auto_fit_to_graph) {
                plotter_NB_UI1.FitToGraph();
            }
            if (fname.endsWith(".xy")) {
                plotter_NB_UI1.setGraphFunctionXY();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static private void SetPreferredLookAndFeel() {
        try {
            String pref_laf_string = null;
            File pref_laf = new File(System.getProperty("user.home"), ".java_diag_preferred_laf");
            if (pref_laf.exists() && pref_laf.canRead()) {
                BufferedReader br = new BufferedReader(new FileReader(pref_laf));
                pref_laf_string = br.readLine().trim();
                br.close();
                if (null != pref_laf_string && pref_laf_string.length() > 1) {
                    UIManager.setLookAndFeel(pref_laf_string);
                }
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    public static void setForcedLineFilterPattern(String _ForcedLineFilterPattern,
            boolean _use_forced_line_filter_pattern) {
        PlotLoader.setForcedLineFilterPattern(_ForcedLineFilterPattern,
                _use_forced_line_filter_pattern);
    }

    public static void lock_value_for_plot_versus_line_number(
            boolean _plot_verses_line_number,
            boolean _plot_verses_line_number_locked) {
        PlotLoader.lock_value_for_plot_versus_line_number(_plot_verses_line_number,
                _plot_verses_line_number_locked);
    }

    public static void setFieldSeparator(String _FIELD_SEPARATOR) {
        PlotLoader.setFieldSeparator(_FIELD_SEPARATOR);
    }

    public void SaveFile(String fileName) {
        this.plotter_NB_UI1.SaveFile(fileName);
    }

    public double getXMin() {
        return this.plotter_NB_UI1.getXMin();
    }

    public double getXMax() {
        return this.plotter_NB_UI1.getXMax();
    }

    public double getYMin() {
        return this.plotter_NB_UI1.getYMin();
    }

    public double getYMax() {
        return this.plotter_NB_UI1.getYMax();
    }

    public void setUseShortname(boolean _UseShortName) {
        this.plotter_NB_UI1.setUseShortname(_UseShortName);
    }

    /**
     * Main -- opens and displays a new Frame reading in optional files to plot.
     *
     * @param _args the command line arguments or list of CSV files to plot.
     */
    public static void main(String _args[]) {
        try {
            boolean hide = false;
            boolean next_arg_is_output_file = false;
            String output_filename = null;
            boolean output_file_is_csv = false;
            boolean output_file_is_stats = false;
            String combined_arg = "";
            for (String a : _args) {
                if (a.compareTo("--hide") == 0) {
                    hide = true;
                    continue;
                } else if (a.compareTo("-o") == 0) {
                    next_arg_is_output_file = true;
                    continue;
                }
                if (next_arg_is_output_file) {
                    output_filename = a;
                    if (output_filename.endsWith(".csv")) {
                        output_file_is_csv = true;
                    } else if (output_filename.endsWith(".stats")) {
                        output_file_is_stats = true;
                    } else if (!output_filename.endsWith(".jpg")) {
                        output_filename += ".jpg";
                    }
                    hide = true;
                    next_arg_is_output_file = false;
                    continue;
                }
                combined_arg += " " + a;
            }
            System.out.println("Starting " + plotterJFrame.class.getCanonicalName() + " " + combined_arg + " using java " + System.getProperty("java.version"));
            final String fargs[] = _args;
            if (!hide) {
                SetPreferredLookAndFeel();
                java.awt.EventQueue.invokeLater(new Runnable() {

                    public void run() {
                        new plotterJFrame(fargs).setVisible(true);
                    }
                });
            } else {
                System.out.println("Running in command-line mode.");
                PlotLoader.cmd_line_mode = true;
                final String output_filename_final = output_filename;
                final plotterJFrame plotter = new plotterJFrame(_args);
                Thread.sleep(50);
                final boolean is_csv = output_file_is_csv;
                final boolean is_stats = output_file_is_stats;
                java.awt.EventQueue.invokeLater(new Runnable() {

                    public void run() {
                        try {
                            if (!is_csv && !is_stats) {
                                BufferedImage bi = plotter.plotToImage();
                                try {
                                    ImageIO.write(bi, "JPEG", new File(output_filename_final));
                                } catch (IOException iOException) {
                                    iOException.printStackTrace();
                                }
                            } else if (is_csv) {
                                plotter.SaveFile(output_filename_final);
                            } else if (is_stats) {
                                plotter.plotter_NB_UI1.SaveStatsFile(new File(output_filename_final));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            System.exit(1);
                        }
                        System.exit(0);
                    }
                });

            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItemDebug;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenu jMenuExtras;
    private javax.swing.JMenu jMenuFile;
    private javax.swing.JMenu jMenuFileRecent;
    private javax.swing.JMenuItem jMenuItemExit;
    private javax.swing.JMenuItem jMenuItemFileOpen;
    private javax.swing.JMenuItem jMenuItemRandomContinous;
    private javax.swing.JMenuItem jMenuItemRandomTest;
    private javax.swing.JMenuItem jMenuItemReload;
    private javax.swing.JMenuItem jMenuItemResetMinXToZero;
    private javax.swing.JMenuItem jMenuItemSave;
    private javax.swing.JMenuItem jMenuItemSaveImage;
    private javax.swing.JMenuItem jMenuItemShowDataFrame;
    private javax.swing.JMenuItem jMenuItemShowOptions;
    private javax.swing.JMenuItem jMenuItemSineTest;
    private javax.swing.JMenuItem jMenuItemStopRandomContinous;
    private javax.swing.JMenu jMenuTests;
    private diagapplet.plotter.plotter_NB_UI plotter_NB_UI1;
    // End of variables declaration//GEN-END:variables
}
